#!/bin/bash

# MD2PPT 健康检查脚本
# 用于监控服务状态和性能

set -e

# 配置
API_URL="${API_URL:-http://localhost:8000}"
TIMEOUT="${TIMEOUT:-10}"
ALERT_EMAIL="${ALERT_EMAIL:-admin@example.com}"

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

# 日志函数
log_info() {
    echo -e "${BLUE}[$(date '+%Y-%m-%d %H:%M:%S')] INFO:${NC} $1"
}

log_success() {
    echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')] SUCCESS:${NC} $1"
}

log_warning() {
    echo -e "${YELLOW}[$(date '+%Y-%m-%d %H:%M:%S')] WARNING:${NC} $1"
}

log_error() {
    echo -e "${RED}[$(date '+%Y-%m-%d %H:%M:%S')] ERROR:${NC} $1"
}

# 发送告警
send_alert() {
    local message="$1"
    local severity="$2"
    
    log_error "$message"
    
    # 发送邮件告警（如果配置了邮件）
    if command -v mail &> /dev/null && [ -n "$ALERT_EMAIL" ]; then
        echo "$message" | mail -s "[MD2PPT] $severity Alert" "$ALERT_EMAIL"
    fi
    
    # 发送到 Slack（如果配置了 Webhook）
    if [ -n "$SLACK_WEBHOOK" ]; then
        curl -X POST -H 'Content-type: application/json' \
            --data "{\"text\":\"🚨 MD2PPT Alert: $message\"}" \
            "$SLACK_WEBHOOK"
    fi
}

# 检查 API 服务
check_api_health() {
    log_info "检查 API 服务健康状态..."
    
    local health_url="$API_URL/health"
    local response
    local http_code
    
    # 发送健康检查请求
    response=$(curl -s -w "%{http_code}" --max-time "$TIMEOUT" "$health_url" || echo "000")
    http_code="${response: -3}"
    
    if [ "$http_code" = "200" ]; then
        log_success "API 服务健康 (HTTP $http_code)"
        return 0
    else
        send_alert "API 服务异常: HTTP $http_code" "CRITICAL"
        return 1
    fi
}

# 检查 API 响应时间
check_api_response_time() {
    log_info "检查 API 响应时间..."
    
    local health_url="$API_URL/health"
    local response_time
    
    response_time=$(curl -s -o /dev/null -w "%{time_total}" --max-time "$TIMEOUT" "$health_url" || echo "999")
    
    if (( $(echo "$response_time < 2.0" | bc -l) )); then
        log_success "API 响应时间正常: ${response_time}s"
        return 0
    elif (( $(echo "$response_time < 5.0" | bc -l) )); then
        log_warning "API 响应时间较慢: ${response_time}s"
        return 0
    else
        send_alert "API 响应时间过慢: ${response_time}s" "WARNING"
        return 1
    fi
}

# 测试转换功能
test_conversion() {
    log_info "测试转换功能..."
    
    local convert_url="$API_URL/api/v1/convert"
    local test_data='{
        "markdown_content": "# Health Check Test\n\n## Test Section\n- Test item 1\n- Test item 2",
        "options": {"theme": "default"}
    }'
    
    local response
    local http_code
    
    response=$(curl -s -w "%{http_code}" --max-time "$TIMEOUT" \
        -X POST "$convert_url" \
        -H "Content-Type: application/json" \
        -d "$test_data" || echo "000")
    
    http_code="${response: -3}"
    
    if [ "$http_code" = "200" ]; then
        # 检查响应是否包含成功标识
        if echo "$response" | grep -q '"success":[[:space:]]*true'; then
            log_success "转换功能正常"
            return 0
        else
            send_alert "转换功能返回错误响应" "WARNING"
            return 1
        fi
    else
        send_alert "转换功能异常: HTTP $http_code" "CRITICAL"
        return 1
    fi
}

# 检查主题接口
check_themes_api() {
    log_info "检查主题接口..."
    
    local themes_url="$API_URL/api/v1/themes"
    local response
    local http_code
    
    response=$(curl -s -w "%{http_code}" --max-time "$TIMEOUT" "$themes_url" || echo "000")
    http_code="${response: -3}"
    
    if [ "$http_code" = "200" ]; then
        if echo "$response" | grep -q '"themes"'; then
            log_success "主题接口正常"
            return 0
        else
            send_alert "主题接口返回异常数据" "WARNING"
            return 1
        fi
    else
        send_alert "主题接口异常: HTTP $http_code" "WARNING"
        return 1
    fi
}

# 检查 Docker 容器状态
check_docker_containers() {
    log_info "检查 Docker 容器状态..."
    
    if ! command -v docker &> /dev/null; then
        log_warning "Docker 命令不可用，跳过容器检查"
        return 0
    fi
    
    local containers=("md2ppt-api" "md2ppt-mcp")
    local failed_containers=()
    
    for container in "${containers[@]}"; do
        if docker ps --format "table {{.Names}}" | grep -q "$container"; then
            log_success "容器 $container 运行正常"
        else
            failed_containers+=("$container")
            log_error "容器 $container 未运行"
        fi
    done
    
    if [ ${#failed_containers[@]} -gt 0 ]; then
        send_alert "容器异常: ${failed_containers[*]}" "CRITICAL"
        return 1
    fi
    
    return 0
}

# 检查磁盘空间
check_disk_space() {
    log_info "检查磁盘空间..."
    
    local storage_path="${STORAGE_PATH:-./storage}"
    local usage
    
    if [ -d "$storage_path" ]; then
        usage=$(df "$storage_path" | awk 'NR==2 {print $5}' | sed 's/%//')
        
        if [ "$usage" -lt 80 ]; then
            log_success "磁盘空间充足: ${usage}% 已使用"
        elif [ "$usage" -lt 90 ]; then
            log_warning "磁盘空间紧张: ${usage}% 已使用"
        else
            send_alert "磁盘空间不足: ${usage}% 已使用" "WARNING"
            return 1
        fi
    else
        log_warning "存储路径不存在: $storage_path"
    fi
    
    return 0
}

# 检查内存使用
check_memory_usage() {
    log_info "检查内存使用..."
    
    if command -v docker &> /dev/null; then
        local containers=("md2ppt-api" "md2ppt-mcp")
        
        for container in "${containers[@]}"; do
            if docker ps --format "table {{.Names}}" | grep -q "$container"; then
                local mem_usage=$(docker stats --no-stream --format "{{.MemUsage}}" "$container" 2>/dev/null || echo "N/A")
                log_info "容器 $container 内存使用: $mem_usage"
            fi
        done
    fi
    
    # 系统内存使用
    local mem_usage=$(free | awk 'NR==2{printf "%.0f", $3*100/$2}')
    if [ "$mem_usage" -lt 80 ]; then
        log_success "系统内存使用正常: ${mem_usage}%"
    elif [ "$mem_usage" -lt 90 ]; then
        log_warning "系统内存使用较高: ${mem_usage}%"
    else
        send_alert "系统内存使用过高: ${mem_usage}%" "WARNING"
    fi
}

# 清理过期文件
cleanup_expired_files() {
    log_info "清理过期文件..."
    
    local cleanup_url="$API_URL/api/v1/cleanup"
    local response
    local http_code
    
    response=$(curl -s -w "%{http_code}" --max-time "$TIMEOUT" "$cleanup_url" || echo "000")
    http_code="${response: -3}"
    
    if [ "$http_code" = "200" ]; then
        log_success "过期文件清理完成"
    else
        log_warning "过期文件清理失败: HTTP $http_code"
    fi
}

# 生成健康报告
generate_health_report() {
    local report_file="health_report_$(date +%Y%m%d_%H%M%S).json"
    
    log_info "生成健康报告: $report_file"
    
    cat > "$report_file" << EOF
{
    "timestamp": "$(date -Iseconds)",
    "api_health": $(check_api_health >/dev/null 2>&1 && echo "true" || echo "false"),
    "conversion_test": $(test_conversion >/dev/null 2>&1 && echo "true" || echo "false"),
    "themes_api": $(check_themes_api >/dev/null 2>&1 && echo "true" || echo "false"),
    "docker_containers": $(check_docker_containers >/dev/null 2>&1 && echo "true" || echo "false"),
    "disk_space_ok": $(check_disk_space >/dev/null 2>&1 && echo "true" || echo "false"),
    "system_info": {
        "hostname": "$(hostname)",
        "uptime": "$(uptime -p 2>/dev/null || echo 'N/A')",
        "load_average": "$(uptime | awk '{print $NF}')"
    }
}
EOF
    
    log_success "健康报告已生成: $report_file"
}

# 主健康检查函数
run_health_check() {
    local overall_status=0
    
    echo "================================"
    echo "    MD2PPT 健康检查报告"
    echo "    时间: $(date)"
    echo "================================"
    echo ""
    
    # 执行各项检查
    check_api_health || overall_status=1
    check_api_response_time || overall_status=1
    test_conversion || overall_status=1
    check_themes_api || overall_status=1
    check_docker_containers || overall_status=1
    check_disk_space || overall_status=1
    check_memory_usage || overall_status=1
    
    echo ""
    echo "================================"
    
    if [ $overall_status -eq 0 ]; then
        log_success "所有健康检查通过 ✅"
    else
        log_error "部分健康检查失败 ❌"
    fi
    
    echo "================================"
    
    return $overall_status
}

# 监控模式（持续监控）
monitor_mode() {
    log_info "启动监控模式..."
    
    local check_interval="${CHECK_INTERVAL:-300}"  # 默认5分钟
    
    while true; do
        echo ""
        log_info "=== 执行定时健康检查 ==="
        
        if ! run_health_check; then
            log_error "健康检查发现问题，请检查服务状态"
        fi
        
        # 清理过期文件
        cleanup_expired_files
        
        log_info "下次检查将在 $check_interval 秒后进行"
        sleep "$check_interval"
    done
}

# 使用说明
usage() {
    echo "MD2PPT 健康检查脚本"
    echo ""
    echo "使用方法: $0 [选项]"
    echo ""
    echo "选项:"
    echo "  -h, --help          显示帮助信息"
    echo "  -c, --check         执行一次健康检查（默认）"
    echo "  -m, --monitor       启动监控模式"
    echo "  -r, --report        生成健康报告"
    echo "  -t, --test          仅测试转换功能"
    echo "  --cleanup           清理过期文件"
    echo ""
    echo "环境变量:"
    echo "  API_URL             API 服务地址 (默认: http://localhost:8000)"
    echo "  TIMEOUT             请求超时时间 (默认: 10)"
    echo "  ALERT_EMAIL         告警邮箱地址"
    echo "  SLACK_WEBHOOK       Slack Webhook URL"
    echo "  CHECK_INTERVAL      监控检查间隔 (默认: 300秒)"
    echo ""
    echo "示例:"
    echo "  $0 --check"
    echo "  API_URL=http://prod.example.com:8000 $0 --monitor"
    echo "  $0 --test"
}

# 主函数
main() {
    case "${1:-check}" in
        "-h"|"--help")
            usage
            ;;
        "-c"|"--check"|"check")
            run_health_check
            ;;
        "-m"|"--monitor"|"monitor")
            monitor_mode
            ;;
        "-r"|"--report"|"report")
            generate_health_report
            ;;
        "-t"|"--test"|"test")
            test_conversion
            ;;
        "--cleanup"|"cleanup")
            cleanup_expired_files
            ;;
        *)
            echo "未知选项: $1"
            echo "使用 --help 查看帮助信息"
            exit 1
            ;;
    esac
}

# 执行主函数
main "$@"